//Flow
//@flow


//类型注解
//babel能够自动消除

function sum(a: number, b: number) {
    return a + b
}

console.log(sum(100, 100)); //No errors!
//console.log(sum(100, "100")) //flow language support插件能够直接在文件中显示类型错误
//flowr报错：Cannot call `sum` with `"100"` bound to `b` because string [1] is incompatible with number [2]. [incompatible-call]


//flow类型推断
//大部分情况下，flow能够推断出来参数的类型
function square(n) {
    return n * n
}
//square('100');

let num: number = 100; //类型注解限制了变量只能是number类型
//num = "100";

function foo(): number {
    return 100
        //return "100";
}

function bar(): void {
    //没有返回值应当标记函数为void
}

//原始类型
const a: string = 'footer';
const b: number = Infinity; //NaN、100
const c: boolean = false; //true
const d: null = null;
const e: void = undefined;
//const f: symbol = Symbol()

//数组类型

const arr1: Array < number >= [1, 2, 3];
const arr2: number[] = [1, 2, 3];
//元组
//const foo: [string, number] = ['foo', 100];

//对象类型
const obj1: { foo: string, bar: number } = { foo: 'string', bar: 100 };
const obj2: { foo ? : string, bar: number } = { bar: 100 }; //？号表示可选
const obj3: {
    [string]: string
} = {}
obj3.key1 = 'value';
//obj3.key2 = 100//键值都被限制成了string类型

//函数类型
function foo1(callback: (string, number) => void) { //限制回调函数有两个参数且分别为string 和数字
    callback('string', 100)
}

foo1(function(str, n) {
    return undefined
})

//特殊类型
//----字面量类型
const a11: 'foo' = 'foo'
const type: 'success' | 'warning' | 'danger' = 'success'; //限制值只能是从这几个中取

//用type定义联合类型
type StringOrNumber = string | number
const b2: StringOrNumber = 'string'; //=100

//maybe类型
const gender: ? number = undefined; //等同于下面一句
//const gender: number | null | void = undefined;

//mixed
//等于联合了所有类型的联合类型
//string|bumber|boolean...
function passMixed(value: mixed) {
    if (typeof value === 'string') {

        value.substr(1)
    }
    if (typeof value === 'number') {
        value * value

    }
}
passMixed('string');
passMixed(100)

//any类型
function passAny(value: any) {
    value.substr(1)
    value * value
}
passAny('string')
passAny(100)

//flow运行环境api
const element: HTMLElement | null = document.getElementById('app');